package com.wangbl.manager;

import java.util.HashMap;
import java.util.LinkedHashMap;

import com.wangbl.manager.model.DevInfo;
import com.wangbl.manager.utils.Logger;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;

public class ScanDeviceUtil {

	private Context context;
	private BluetoothAdapter adapter;
	private OnSearchReceiveListener listener;

	private BroadcastReceiver receiver;
	private HashMap<String, DevInfo> devInfos = new LinkedHashMap<String, DevInfo>();
	private boolean isCancel;
	private boolean isTimeout;
	private boolean isStartFail;
	private int timeout;
	
	private static final int SEARCH_TIMEOUT = 0;
	private static final int NEVER_RECEIVE_SEARCH_START = 1;
	private static final String TAG = "SearchDeviceUtil";

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch(msg.what) {
			case SEARCH_TIMEOUT:
				Logger.i(TAG,"SEARCH_TIMEOUT");
				isTimeout = true;
				stopSearch();
				break;
			case NEVER_RECEIVE_SEARCH_START:
				Logger.i(TAG,"NEVER_RECEIVE_SEARCH_START");
				isStartFail = true;
				stopSearch();
				break;
			}
		};
	};

	ScanDeviceUtil(Context c) {
		context = c.getApplicationContext();
		registerReceiver();
	}

	private void registerReceiver() {
		receiver = new BTBroadcastReceiver();
		adapter = BluetoothAdapter.getDefaultAdapter();
		IntentFilter filter = new IntentFilter();

		filter.addAction(BluetoothDevice.ACTION_FOUND);
		filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
		filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
		filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
		
		filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
		filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
		filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);

		Intent i = context.registerReceiver(receiver, filter);
		Logger.i(TAG,"register receiver i = " + i);
	}

	/**
	 * 启动搜索蓝牙设备
	 * 
	 * @param timeout
	 *            蓝牙搜索时间
	 * 
	 * @param listener
	 *            打开蓝牙以及发现蓝牙设备的时的回�?{@link OnSearchReceiveListener}
	 */
	public void startDevSearch(int timeout, OnSearchReceiveListener listener) {
		Logger.i(TAG,"startSearchBTDev timeout=" + timeout);
		isCancel = false;
		this.timeout = timeout;
		devInfos.clear();
		boolean resVal;
		this.listener = listener;
		Logger.i(TAG,"adapter state=" + adapter.getState());
		switch (adapter.getState()) {
		case BluetoothAdapter.STATE_ON:
			startDiscovery();
			break;
		case BluetoothAdapter.STATE_OFF:
			resVal = adapter.enable();
			if (!resVal) {
				Intent intent = new Intent(
						BluetoothAdapter.ACTION_REQUEST_ENABLE);
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				context.startActivity(intent);
				listener.startDiscoveryFail();
			}
			break;
		case BluetoothAdapter.STATE_TURNING_OFF:
			listener.stateTurningOff();
			break;
		case BluetoothAdapter.STATE_TURNING_ON:
			break;
		}
	}

	private void startDiscovery() {
		Logger.i(TAG,"startDiscovery");
		boolean res = adapter.startDiscovery();
		// FIXME a little waired cannot scan though res == true
		Logger.i(TAG,"startDiscovery result=" + res);
		if (res) {
			startSearchTimer();
		} else {
			Logger.e(TAG,"启动扫描失败");
			adapter.disable();
			listener.startDiscoveryFail();
		}
	}

	private void startSearchTimer() {
		if (!handler.hasMessages(NEVER_RECEIVE_SEARCH_START)) {
			handler.sendEmptyMessageDelayed(NEVER_RECEIVE_SEARCH_START, 5000);
		}
	}

	private void stopSearchTimer() {
		handler.removeMessages(NEVER_RECEIVE_SEARCH_START);
		handler.removeMessages(SEARCH_TIMEOUT);
	}

	private class BTBroadcastReceiver extends BroadcastReceiver {

		@SuppressWarnings("unchecked")
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			Logger.i(TAG,"onReceive");
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				Logger.i(TAG,"ACTION_FOUND");
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				
				String address = device.getAddress();
				DevInfo info = devInfos.get(address);
				if (info == null) {
					info = new DevInfo(device.getName(), device.getAddress());
					devInfos.put(address, info);
				} else if (device.getName() != null) {
					info.setName(device.getName());
				}
				if (listener != null) {
					listener.onFindDevReceive((HashMap<String, DevInfo>) devInfos
							.clone());
				}

			} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
				Logger.i(TAG,"ACTION_STATE_CHANGED:"+adapter.getState());
				final int state = intent.getIntExtra(
						BluetoothAdapter.EXTRA_STATE, adapter.getState());
				switch(state) {
				case BluetoothAdapter.STATE_ON:
					Logger.i(TAG,"STATE_ON");
					startDiscovery();
					break;
				case BluetoothAdapter.STATE_TURNING_OFF:
					Logger.i(TAG,"STATE_TURNING_OFF");
					stopSearch();
					break;
				case BluetoothAdapter.STATE_OFF:
					Logger.i(TAG,"STATE_OFF");
					stopSearch();
					listener.onClosedBtooth();
					break;
				case BluetoothAdapter.STATE_TURNING_ON:
					Logger.i(TAG,"STATE_TURNING_ON");
					break;
				default:
					Logger.i(TAG,"BT STATE CHANGE: " + state);
				}
			} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
					.equals(action)) {
				Logger.i(TAG,"ACTION_DISCOVERY_FINISHED:");
				if (!isCancel) {
					startDiscovery();
				} else if (isTimeout) { 
					isTimeout = false;
					if (listener != null) {
						listener.onFindDevTimeout();
					}
				} else if (isStartFail) {
					isStartFail = false;
					if (listener != null) {
						Logger.e(TAG,"启动扫描失败");
						adapter.disable();
						listener.startDiscoveryFail();
					}
				} else {
					if (listener != null) {
						listener.onFindFinished();
					}
				}

			} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
				Logger.i(TAG,"ACTION_DISCOVERY_STARTED");
				handler.removeMessages(NEVER_RECEIVE_SEARCH_START);
				if (!handler.hasMessages(SEARCH_TIMEOUT)) {
					handler.sendEmptyMessageDelayed(SEARCH_TIMEOUT, timeout);
				}
			} else if (BluetoothDevice.ACTION_NAME_CHANGED.equals(action)) {
				Logger.i(TAG,"ACTION_NAME_CHANGED");
			} else if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)){
				Logger.i(TAG, "ACTION_ACL_DISCONNECTED");
				if(listener != null){
					listener.onConnectLose();
				}
			} else {
				Logger.i(TAG,"other action:"+action);
			}
		}
	}

	public void stopSearch() {
		Logger.i(TAG,"stopSearch");
		isCancel = true;
		adapter.cancelDiscovery();
		stopSearchTimer();
	}

	private void unregisterReceiver() {
		context.unregisterReceiver(receiver);
		receiver = null;
	}

	public void destory() {
		stopSearch();
		unregisterReceiver();
	}

	/**
	 * 发现蓝牙设备时的callback 接口
	 * 
	 * @author wbl
	 *
	 */
	public interface OnSearchReceiveListener {

		void onFindDevTimeout();

		/**
		 * 搜索蓝牙的回调方�?
		 * 
		 * @param info
		 *            蓝牙设备的信息对象，包含蓝牙name，蓝牙mac地址
		 */
		void onFindDevReceive(HashMap<String, DevInfo> devInfos);

		/**
		 * 蓝牙正在关闭
		 */
		void stateTurningOff();

		/**
		 * 启动蓝牙搜索失败
		 */
		void startDiscoveryFail();

		void onFindFinished();

		void onClosedBtooth();
		
		void onConnectLose();
	}
}
